#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/select.h>
#include <unistd.h>
#include <pthread.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdarg.h>


#include "p_lib.h"


int str2Hex(char *src, unsigned char *dst, int src_len)
{
	int i = 0;
	int j;
	int temp = 0;
	unsigned char buf[2];

	char *p_src = src;
	unsigned char *p_dst = dst;
	const char List_Capital[16] =
	{
		'0', '1', '2', '3',
		'4', '5', '6', '7',
		'8', '9', 'A', 'B',
		'C', 'D', 'E', 'F',
	};

	const char List_Small[16] =
	{
		'0', '1', '2', '3',
		'4', '5', '6', '7',
		'8', '9', 'a', 'b',
		'c', 'd', 'e', 'f',
	};

	do{
		memcpy(buf, p_src, 2);
		*p_dst = 0x00;
		j = 0;
		do{
			if((buf[0] == List_Capital[j]) || (buf[0] == List_Small[j]))//High half Byte
			{
				*p_dst = (j << 4);
				break;
			}
			j++;
		}while(j < 16);
		if(j == 16)
			return 0;

		j = 0;
		do{
			if((buf[1] == List_Capital[j]) || (buf[1] == List_Small[j]))//Low half Byte
			{
				*p_dst += j;
				break;
			}
			j++;
		}while(j < 16);
		if(j == 16)
			return 0;

		p_dst++;
		p_src += 2;
		i += 2;
	}while(i < src_len);

	return 1;
}

int Hex2String(unsigned char *src, char *dst, int src_len)
{
	int i;
	unsigned char temp;
	const char List[16] =
	{
		'0','1','2','3',
		'4','5','6','7',
		'8','9','A','B',
		'C','D','E','F',
	};

	for(i = 0; i < src_len; i++)
	{
		temp = (((src[i]) >> 4) & 0x0F);
		*(dst+2*i) = List[temp];
		temp = (src[i] & 0x0F);
		*(dst + 2*i + 1) = List[temp];
	}

	*(dst+2*i) = '\0';

	return 2 * i;
}

/**/
int str_PickUp(char *Src, char *sStart, char *sEnd, char *Dst)
{
	char * p_start = NULL;
	char * p_end = NULL;
	int len = 0;
	p_start = strstr(Src, sStart);
	if(!p_start)
		return -1;

	p_start += strlen(sStart);

	p_end = strstr(p_start, sEnd);
	if(!p_end)
	{
		len = strlen(p_start);
		strcpy(Dst, p_start);
	}
	else
	{
		len = p_end - p_start;
		strncpy(Dst, p_start, len);
		Dst[len] = '\0';
	}

	return len;
}

long FileCopy(char *From, char *To)
{
	FILE *p_From = NULL;
	FILE *p_To = NULL;
	long file_size = 0;
	int data = 0;

	p_To  = fopen(To, "wb+");
	p_From = fopen(From, "rb");
	if((p_From == NULL)||(p_To == NULL))
	{
		if(p_To != NULL)
			fclose(p_To);

		return -1;
	}

	while(1)
	{
		data = fgetc(p_From);
		if(feof(p_From))
		{
			fclose(p_From);
			fclose(p_To);
			break;
		}

		if(fputc(data, p_To))
			file_size++;
	}

	return file_size;
}

int Delay(long sec, long ms)
{
	struct timeval tv;
    tv.tv_sec = sec;
    tv.tv_usec = ms*1000;

    return select(0, NULL, NULL, NULL, &tv);
}

unsigned long get_file_size(const char *path)
{
    unsigned long filesize = 0;
    struct stat statbuff;
	if(NULL == path)
		return 0;

    if(0 == stat(path, &statbuff))
        filesize = statbuff.st_size;

    return filesize;
}

void PrintDebuf(const char *msgInfo, const unsigned char *pucBuf, int iLen)
{
	int i = 0;

	if(msgInfo != NULL)
		DBUG("%s", msgInfo);

	if(pucBuf == NULL)
		return;

	for(i = 0; i < iLen; i++)
		DBUG("%02x ", pucBuf[i]);

	DBUG("\n");

	return ;
}

unsigned char cs_mod_256(unsigned char *Buf, int iLen)
{
	unsigned char CS = 0;
	int i = 0;
	if(Buf == NULL)
		return 0;

	for(i = 0; i < iLen; i++)
		CS += Buf[i];

	return CS;
}

int FileCpWithCs(char *DstFile, char *SrcFile)
{
	int i = 0;
	int status = 0;
	char cmd[512]={0};

	if((DstFile==NULL)||(SrcFile==NULL))
	{
		DBUG( "[FileCpWithCs]:Para error\n");
		return -1;
	}

	if(0 == access(DstFile,F_OK))
	{
		while(i<3)
		{
			if(0 == remove(DstFile))
				break;
			i++;
		}

		if(i >= 3)
		{
			DBUG( "[FileCpWithCs]rm file %s fail:%s\n", DstFile, strerror(errno));
			return -2;
		}
	}

	if(0 != access(SrcFile, F_OK))
	{
		DBUG( "[FileCpWithCs]Fatal error,SrcFile %s not exist\n",SrcFile);
		return -3;
	}

	DBUG("cp %s %s", SrcFile, DstFile);
	i = 0;

	while(i<3)
	{
		i++;
		DBUG( "[FileCpWithCs] ***** %s **** excute %d start\n", cmd, i);
		status = FileCopy(SrcFile, DstFile);
		if(status < 0)
		{
			DBUG( "[FileCpWithCs]%s fail\n", cmd);
			continue;
		}

		DBUG( "[FileCpWithCs] ((((( %s )))) excute %d Finish\n", cmd, i);
		if(0 != access(DstFile, F_OK))
		{
			DBUG( "[FileCpWithCs]%s result fail\n", cmd);
			continue;
		}
		DBUG( "[FileCpWithCs] ###### %s ###### excute %d success!!!!\n", cmd, i);
		break;
	}

	if(i>=3)
		return -6;

	remove(SrcFile);

	return 1;
}


int File_Update(char *FileName, unsigned char *Src, int iLen, int iOffset)
{
	int tempLen = 0;
	int fd = -1;
	int status = 0;

	if((FileName == NULL)||(Src == NULL))
	{
		DBUG( "parameter error\n ");
		return -1;
	}

	fd = open(FileName, O_RDWR , 0777);
	if(fd < 0)
	{
		DBUG( "open %s faild, the err is %s\n", FileName, strerror(errno));
		return -2;
	}

	status = lseek(fd, iOffset, SEEK_SET);
	if(status < 0)
	{
		close(fd);
		DBUG( "lseek %s faild, the err is %s\n", FileName, strerror(errno));
		return -3;
	}

	status = write(fd, Src, iLen);
	if(status < 0)
	{
		DBUG( "write %s faild, the err is %s\n", FileName, strerror(errno));
	}
	close(fd);

	return status;
}

int write_data(unsigned char *Buf, int iLen, int fd)
{
	int i = 0;
	int status = 0;

	if(fd <= 0 )
	{
		DBUG("[write_sim_data] Android_Socket_fd <= 0\n");
		return -1;
	}

//	for(i = 0; i < iLen; i++)
//	{
		status = write(fd , Buf, iLen);
		if(status < 0)
		{
			DBUG( "[write_sim_data]:write sim uart error\n");
			return -2;
		}
//	}

	return iLen;
}

int read_data(unsigned char *Buf, int iLen, int iTimeOut, int fd)
{
	int i = 0;
	int iRetLen = 0;
	int iCurLen = 0;
	int iOffset = 0;
	int iExpLen = 0;

	if(fd <= 0 )
	{
		DBUG( "[read_sim_data] Android_Socket_fd <= 0\n");
		return -1;
	}

	iExpLen = iLen;
	while(i < iTimeOut)
	{
		iCurLen = read(fd, Buf+iOffset, iExpLen);
		if(iCurLen > 0)
		{
			iExpLen -= iCurLen;
			iRetLen += iCurLen;
			iOffset += iCurLen;
		}
		if(iRetLen >= iLen) break;
		Delay(0, 10);
		i++;
	}

	return iRetLen;
}

int Check_Dir_By_Name(char *Path)
{
	char cmd[200];
    if(0 != access(Path, 0))
        if(mkdir(Path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH))
			DBUG( "mkdir %s faild, the err is %s\n", Path, strerror(errno));

	return 0;
}

int Create_File_By_Name(char *FileName)
{
    int fd;

    fd = open(FileName, O_RDWR | O_CREAT | O_TRUNC, 0777);
    if(fd < 0)
    {
        DBUG( "open file %s fail, err is %s\n", FileName, strerror(errno));
        return -1;
    }
	close(fd);

	return 0;
}

int Write_File_By_New(char *FileName, char *Src, int len)
{
	int Ret;
    int fd;
    char p_Buf[10] = {0};

    fd = open(FileName, O_RDWR | O_CREAT | O_TRUNC, 0777);
    if(fd < 0)
    {
        DBUG( "open file %s fail, err is %s\n", FileName, strerror(errno));
        return -1;
    }

    Ret = write(fd, Src, len);
    if(Ret < 0)
    {
        DBUG( "writ file %s data fail, err is %s\n", FileName, strerror(errno));
        close(fd);
        return -2;
    }
    close(fd);

	return 0;
}

int Write_File_By_OrverFlow(char *FileName, char *Src, int len)
{
	int Fd = 0;
	int count = 0;

	if(access(FileName, F_OK)!=0)
        return -1;

    Fd = open(FileName, O_RDWR, 0777);
    if(Fd < 0)
    {
        DBUG( "the %s open faild, err is %s\n", FileName, strerror(errno));
        return -2;
    }

    count = write(Fd, Src, len);
    if(count < 0)
    {
        DBUG( "write %s faild, err is %s\n", FileName, strerror(errno));
        close(Fd);
        return -3;
    }
    close(Fd);

	return 0;
}

int Check_FileSzie_By_Clear(char *FileName)
{
	unsigned long file_size = 0;
    int fd = 0;

    if(!access(FileName, F_OK))
    {
        file_size = get_file_size(FileName);
        if(file_size > 409600)
        {
            DBUG( "file %s is too large, delete it now\n", FileName);
ret:
    		//fd = open(FileName, O_RDWR | O_CREAT | O_TRUNC, 0666);
    		//close(fd);
    		remove(FileName); //by zhangly
		}
    }
    else
    {
        DBUG( "file %s not exist create now\n", FileName);
		goto ret;
    }


	return 0;
}

int Close_FILE(FILE *Fd)
{
	if(Fd)
	{
		fclose(Fd);
		Fd = NULL;
	}

	return 0;
}

int Close_Socket(int *Fd)
{
	if(*Fd > 0)
	{
		close(*Fd);
		*Fd = 0;
	}

	return 0;
}

int Send_Pipe_Cmd(int cmd, int fd)
{
    char buff[4] = {'\0'};

	DBUG("%04d", cmd);

    return write(fd, buff, sizeof(buff));
}

void Creat_New_Thread(void *(*func)(void *))
{
    int State;
    pthread_t pid;

    State = pthread_create(&pid, NULL, func, NULL);
    if(State != 0)
    {
        DBUG( "pthread_create error is %s\n", strerror(errno));
		return;
    }

    pthread_detach(pid);

    return;
}

void log_printf(const char *file, const char *function, int line, const char *fmt, ...)
{
    va_list pArg;
    va_start(pArg, fmt);
    char buf[4096];
    int n = vsprintf(buf, fmt, pArg);
    buf[n] = '\0';
    va_end(pArg);
    printf("%s, %s:%d %s \n", file, function,line, buf);
#ifdef ANDROID
	__android_log_print(ANDROID_LOG_DEBUG,TAG,"%s", buf);
#endif
    fflush(stdout);
}
